// 公共错误code
import { errorCode } from '@/core/utils/errorCode'
// http响应状态码
import { HttpStatus } from '@/core/enums/RespEnum'
import { getToken } from '@/core/utils/auth'
import { tansParams } from '@/core/utils/verulia'
import { decryptBase64, decryptWithAes, encryptBase64, encryptWithAes, generateAesKey } from '@/core/utils/crypto'
import { decrypt, encrypt } from '@/core/utils/jsencrypt'
import $modal from '@/core/plugins/modal'
import $tab from '@/core/plugins/tab'
import useUserStore from '@/store/modules/user.store'
import { isReLogin } from '@/core/utils/request'

const encryptHeader = 'encrypt-key'

export default () => {
  // 全局http配置
  uni.$uv.http.setConfig((config) => {
    // #ifndef H5
    config.baseURL = import.meta.env.VITE_APP_BASE_API
    // #endif
    // #ifdef H5
    config.baseURL = '/dev-api'
    config.withCredentials = true
    // #endif
    config.header['clientid'] = import.meta.env.VITE_APP_CLIENT_ID
    config.header['Content-Type'] = 'application/json;charset=utf-8'
    return config
  })
  // 请求拦截器
  uni.$uv.http.interceptors.request.use(
    (config) => {
      // 请求是否需要带token
      const isToken = (config.header || {})['isToken'] === false
      // 是否需要加密
      const isEncrypt = (config.header || {})['isEncrypt'] === true
      if (getToken() && !isToken) {
        config.header['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
      }
      // get请求映射params参数
      if (config.method === 'get' && config.params) {
        let url = config.url + '?' + tansParams(config.params)
        url = url.slice(0, -1)
        config.params = {}
        config.url = url
      }
      // 当开启参数加密 [注若开启加密, http调用时注意post|put大小写]
      if (isEncrypt && (config.method === 'post' || config.method === 'put')) {
        // 生成一个 AES 密钥
        const aesKey = generateAesKey()
        config.header[encryptHeader] = encrypt(encryptBase64(aesKey))
        config.data = typeof config.data === 'object' ? encryptWithAes(JSON.stringify(config.data), aesKey) : encryptWithAes(config.data, aesKey)
      }
      return config
    },
    (config) => {
      console.log('request interceptors: ', config)
      return Promise.reject(config)
    }
  )

  // 响应拦截器
  uni.$uv.http.interceptors.response.use(
    (res) => {
      // 加密后的 AES 秘钥
      const keyStr = res.header[encryptHeader]
      // 加密
      if (keyStr != null && keyStr != '') {
        const data = res.data
        // 请求体 AES 解密
        const base64Str = decrypt(keyStr)
        // base64 解码 得到请求头的 AES 秘钥
        const aesKey = decryptBase64(base64Str.toString())
        // aesKey 解码 data
        const decryptData = decryptWithAes(data, aesKey)
        // 将结果 (得到的是 JSON 字符串) 转为 JSON
        res.data = JSON.parse(decryptData)
      }
      // 未设置状态码则默认成功状态
      const code = res.data.code || HttpStatus.SUCCESS
      // 获取错误信息
      const msg = errorCode[code] || res.data.msg || errorCode['default']
      // 二进制数据则直接返回
      if (res.config.responseType === 'blob' || res.config.responseType === 'arraybuffer') {
        return res.data
      }
      if (code === HttpStatus.UNAUTHORIZED) {
        if (!isReLogin.show) {
          isReLogin.show = true
          uni.showModal({
            title: '系统提示',
            content: '登录状态已过期，您可以继续留在该页面，或者重新登录',
            cancelText: '取消',
            confirmText: '重新登录',
            success: function (res) {
              if (res.confirm) {
                isReLogin.show = false
                useUserStore()
                  .logout()
                  .then(() => {
                    $tab.reLaunch('/login')
                  })
              } else {
                isReLogin.show = false
              }
            }
          })
        }
        return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
      } else if (code === HttpStatus.SERVER_ERROR) {
        $modal.msgError(msg)
        return Promise.reject(new Error(msg))
      } else if (code === HttpStatus.WARN) {
        $modal.msgError(msg)
        return Promise.reject(new Error(msg))
      } else if (code === HttpStatus.PARAM_ERROR) {
        $modal.msgError(msg)
        return Promise.reject(new Error(msg))
      } else if (code !== HttpStatus.SUCCESS) {
        $modal.msgError(msg)
        return Promise.reject('error')
      } else {
        return Promise.resolve(res.data)
      }
    },
    (error: any) => {
      let { errMsg } = error
      if (errMsg == 'Network Error') {
        errMsg = '后端接口连接异常'
      } else if (errMsg.includes('timeout')) {
        errMsg = '系统接口请求超时'
      } else if (errMsg.includes('request:fail')) {
        errMsg = '系统接口异常'
      }
      // 统一错误提示
      $modal.msgError(errMsg)
      return Promise.reject(error)
    }
  )
}
